package ch.uzh.ifi.seal.ssqa.importer.cqquery;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sourceforge.clearcase.commandline.CleartoolCommandLine;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.ui.PlatformUI;
import ch.uzh.ifi.seal.ssqa.model.ModelFactory;
import ch.uzh.ifi.seal.ssqa.model.Revision;
import ch.uzh.ifi.seal.ssqa.model.UcmActivity;
import ch.uzh.ifi.seal.ssqa.importer.code.LinesOfCodeCounter;
import ch.uzh.ifi.seal.ssqa.importer.versioncontrol.ClearCaseCommand;

public class CQQueryImporter {
	
	private static final String SEG = "#property#";
	/*Reg Ex*/
	private static final Pattern ACTIVITY_ID_PATTERN = Pattern.compile("activity\\s\"(PF91[0-9]+)\"");
	private static final Pattern CLEARQUEST_ID_PATTERN = Pattern.compile("clearquest\\srecord\\sid:\\s(PF91[0-9]+)");
	private static final Pattern OWNER_PATTERN = Pattern.compile("owner:\\s(\\\\\\w+)");
	private static final Pattern STREAM_PATTERN = Pattern.compile("stream:\\s([\\.\\w\\@\\\\]+)");
	private static final Pattern TITLE_PATTERN = Pattern.compile("title:\\s([\\s\\.\\w\\@\\\\]+)");
	private static final Pattern STATE_PATTERN = Pattern.compile("clearquest\\srecord\\sState:\\s(\\w+)");	
	private static final Pattern CPP_PATTERN = Pattern.compile("([\\\\\\w]+\\.cpp\\@\\@[\\\\\\w]+)");
	private static final Pattern C_HEADER_PATTERN = Pattern.compile("([\\\\\\w]+\\.h\\@\\@[\\\\\\w]+)");
	private static final Pattern C_PATTERN = Pattern.compile("([\\\\\\w]+\\.c\\@\\@[\\\\\\w]+)");
	
	
	public Map<?,?> getResultFromSQLQuery(String sql){
		BufferedReader input = this.executePerlSQLScript(sql);
		Map<String,String[]> issues = new HashMap<String,String[]>();
		String line = "";
		try {
			while ((line = input.readLine()) != null) {
				String[] issue = line.split(SEG);
				if(issue != null){
					issues.put(issue[0], issue);
					System.out.println(issue[0]);
				}
			}
		} catch (IOException e) {
			System.out.println("Error at readLine()");
		}
		return issues;
	}

	
	public Map<String, String[]> getResultFromClearCase(){
		CleartoolCommandLine lsact = new CleartoolCommandLine("lsact");
		lsact.addOption("-l");
		lsact.addElement("PF9100157796");
		System.out.println("#### Start ClearCase Import ##########################################");
		System.out.println(Arrays.toString(lsact.create()));		
		String[] output = null;
		String[] errorOutput = null;
		try {
			Map<String,String[]> cmdResult = new ClearCaseCommand(lsact).execute();
			output = cmdResult.get(ClearCaseCommand.SUCCEED);
			errorOutput = cmdResult.get(ClearCaseCommand.FAIL);
		} catch (Exception e){
			e.printStackTrace();
		}
		if(errorOutput != null && errorOutput.length != 0){
			System.out.println("### Clear Case command executes and returns the following Errors:");
			for(String line: errorOutput){
				System.out.println(line);
			}
		}
		if(output != null){
			for (String activity : output) {
				this.ucmActivity = ModelFactory.eINSTANCE.createUcmActivity();
				parseActivity(activity, this.ucmActivity);
			}
		}
		System.out.println("#### End ClearCase Import ##########################################");
		return null;
	}
	
	private List<Revision> getChangeSet(String activityId){
		List changeSet = new ArrayList<Revision>();
		
		
		
		return changeSet;
	}
	
	
	
	
	private Revision revision;
	
	public Revision getRevision() {
		return revision;
	}


	public void setRevision(Revision revision) {
		this.revision = revision;
	}

	private List<Revision> changeSet;
	
	private UcmActivity ucmActivity;
	
	public UcmActivity getUcmActivity() {
		return ucmActivity;
	}


	public void setUcmActivity(UcmActivity ucmActivity) {
		this.ucmActivity = ucmActivity;
	}


	private void parseActivity(String activity, UcmActivity ucm){						
		
		if (activity != null  &&  !activity.trim().equals("")) {
			String[] lines = activity.split("\r");
			//for (String line : lines){
				//System.out.println(line);
				Matcher matcher = ACTIVITY_ID_PATTERN.matcher(activity);
				while(matcher.find()){
					// ucm activity id
					ucm.setIdentifier(matcher.replaceAll("$1"));
					System.out.println("Activity ID: " + matcher.replaceAll("$1"));
				}
				matcher = CLEARQUEST_ID_PATTERN.matcher(activity);
				while(matcher.find()){
					// clear quest id
					// TODO: verify whether there is the issue in the issue list
					System.out.println("clearquest ID: " + matcher.replaceAll("$1"));
				}
				matcher = OWNER_PATTERN .matcher(activity);
				while(matcher.find()){
					// owner
					
					System.out.println("owner: " + matcher.replaceAll("$1"));
				}
				matcher = STREAM_PATTERN.matcher(activity);
				while(matcher.find()){
					// stream
					System.out.println("stream: " + matcher.replaceAll("$1"));
				}
				matcher = TITLE_PATTERN.matcher(activity);
				while(matcher.find()){
					// title for further analysis
					ucm.setHeadline(matcher.replaceAll("$1"));
					System.out.println("title: " + matcher.replaceAll("$1"));
				}
				matcher = STATE_PATTERN.matcher(activity);
				while(matcher.find()){
					// state
					System.out.println("state: " + matcher.replaceAll("$1"));
				}
				
				
				parseRevision(activity, CPP_PATTERN);
				parseRevision(activity, C_HEADER_PATTERN);
				parseRevision(activity, C_PATTERN);
			//}					
		}
	}
	
	private int calculateLOC(String filePath) throws FileNotFoundException{
		int loc = 0;		
		InputStream fileStream = new FileInputStream("Z:" + filePath);
		loc = new LinesOfCodeCounter(fileStream).getCodeLines();
		return loc;
	}
	
	
	private int calculateCycComplexity(String filePath){
		int cycComplexity = 0;
		try {
			
			
			InputStream fileStream = new FileInputStream("Z:" + filePath);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		
		return cycComplexity;
	}
	
	
	private List<Revision> parseRevision(String revisionStr, Pattern pattern){
		List<Revision> result = new ArrayList<Revision>();
		Matcher matcher = pattern.matcher(revisionStr);
		while(matcher.find()){
			Revision revision = ModelFactory.eINSTANCE.createRevision();
			String wholePath = matcher.replaceAll("$1");
			String[] splitWhole = wholePath.split("@@");			
			String fileName = splitWhole[0].replaceAll("\\\\", "/");
			String filePath = wholePath.replaceAll("\\\\", "/").trim();
			int revisionNumber = Integer.parseInt(String.valueOf(filePath.charAt(filePath.length()-1)));
			revision.setFilePath(fileName);
			revision.setRevisionFilePath(filePath);
			revision.setRevisionNumber(revisionNumber);
			int loc;
			try {
				loc = calculateLOC(filePath);
				System.out.println("revision: " + fileName +  "\n loc: " + loc);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			result.add(revision);
			System.out.println("revision: " + fileName + "\n filepath: " + filePath + "\n revision: " + revisionNumber);
		}
		return result;
	}


	private BufferedReader executePerlSQLScript(String sql){
		String path;
		try {
			path = FileLocator.toFileURL(Platform.getBundle("ch.uzh.ifi.seal.ssqa").getEntry("/scripts/")).getPath();
			path = (path.startsWith("/")) ? path.replaceFirst("/", "") : path;
			String command = "ratlperl "+path+"cq_sql.pl \""+sql+"\"";
			Runtime rt = Runtime.getRuntime();
			Process pr = rt.exec(command);
			BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
			return input;
		} catch (IOException e) {
			Status status = new Status(IStatus.ERROR, "My Plug-in ID", 0, "There is no ClearQuest instance around.", null);
			ErrorDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), "ClearQuest Error", "There is no ClearQuest instance around.", status);
			System.out.println("No ClearQuest accessible");
			return null;
		}
}
}
